
#include "ConveyorAgent.h"
#include "FactoryControlSystemAgent.h"
#include "Kit.h"

ConveyorAgent::ConveyorAgent(std::string name, ConveyorType type)
	: Agent(name)
{
	myType = type;

	guiConveyor = NULL;
	FCS = NULL;
	kitRobot = NULL;
		
	kitRecipes  = list<KitRecipe*>();
	currentKit = NULL;

	kitSemaphore = Sema(0);
}

ConveyorAgent::~ConveyorAgent() {
	
}


//Messages

void ConveyorAgent::msgHereAreKits(KitRecipe *kitRecipe){
	{
	ScopedLock lockingItUp (&conveyorLock);
	kitRecipes.push_back(kitRecipe);
	}
	stateChanged();
}

void ConveyorAgent::msgHereIsFinishedKit(KitInterface* k) {
	{
	ScopedLock lockingItUp (&conveyorLock);
	finishedKits.push_back(k);
	}
	stateChanged();
}

void ConveyorAgent::msgKitEndOfConveyor(Kit* kit){
	currentKit=kit;
	stateChanged();
}
void ConveyorAgent::msgKitPickedUp(){
	kitSemaphore.post();
}



//Scheduler

bool ConveyorAgent::pickAndExecuteAnAction(){
	
	if(kitRecipes.size()>0){
		tellGuiToProduceKit(kitRecipes.front());
		return true;
	}
	if(finishedKits.size() >0) {
		tellGuiToPickUpFinishedKit(finishedKits.front());
		return true;
	}

	if(currentKit!=NULL){
		handleKitEndConveyor();
		return true;
	}

	return false;
}


//Actions

void ConveyorAgent::tellGuiToProduceKit(KitRecipe* kit){
	guiConveyor->DoCreateKit(kit);
		{
	ScopedLock lockingItUp (&conveyorLock);
	kitRecipes.pop_front();
		}

}

void ConveyorAgent::tellGuiToPickUpFinishedKit(KitInterface* kit) {
	this->finishedKits.remove(kit);
	if (guiConveyor != NULL)
	{
		guiConveyor->DoSendKitOut((Kit*) kit);
	}
}

//others

void ConveyorAgent::handleKitEndConveyor(){
	if(myType==Conveyor_In){
		kitRobot->msgHereIsKit(currentKit);
		kitSemaphore.wait();
		currentKit=NULL;
		guiConveyor->DoKitTaken();
	}
	else{
		if(myType==Conveyor_OutGood)
			FCS->msgHereIsFinishedKit(currentKit);	
		guiConveyor->DoPurgeKit();//this tells the gui to get rid of the kids
		currentKit=NULL;
	}
}

void ConveyorAgent::setGUI(GUIConveyor* g){
	guiConveyor=g;
}
void ConveyorAgent::setKitRobot(KitRobot* kit){
	kitRobot=kit;
}

QPoint ConveyorAgent::getPickUpKitPosition()
{
	print("ConveyorAgent::getPickUpKitPosition");
	return this->guiConveyor->getPickUpKitPosition();
}

QPoint ConveyorAgent::getDropOffKitPosition() {
	print("ConveyorAgent::getDropOffKitPosition");
	return this->guiConveyor->getDropOffKitPosition();
}

std::string ConveyorAgent::toString() const
{
	return "Conveyor " + getName();
}

// Getters

std::list<KitRecipe*>& ConveyorAgent::getKitRecipes()
{
	return (kitRecipes);
}

// Setters
void ConveyorAgent::setFCS(FactoryControlSystem* fcs)
{
	FCS = fcs;
}

void ConveyorAgent::handleBreak() {
	this->guiConveyor->DoBreak();
}
void ConveyorAgent::handleFix() {
	this->guiConveyor->DoFix();
}

//	
////Messages
//
//void ConveyorAgent::msgKitEndOfConveyor(Kit* k)
//{
//	print("ConveyorAgent::msgKitEndOfConveyor");
//
//	for (std::list<MyKit*>::iterator it = myKits.begin(); it != myKits.end(); it++)
//	{
//		if ( (*it)->kit == k)
//		{
//			print("ConveyorAgent::msgKitEndOfConveyor found kit");
//			(*it)->state = EndOfConveyor;
//			stateChanged();
//			return;
//		}
//	}
//
//	myKits.push_back(new MyKit(k, EndOfConveyor));
//	stateChanged();
//}
//
////From FCS
//void ConveyorAgent::msgHereAreKits(KitRecipe* kitRecipe)
//{
//	print("Received msgHereAreKits");
//	MyKitRecipe myKitRecipe;
//	myKitRecipe.recipe = (*kitRecipe);
//	myKitRecipe.state = KitState::BeginningOfConveyor;
//	this->myRecipes.push_back( myKitRecipe );
//	//MyKit* kit = new MyKit( (Kit*) k, this->Moving);
//	//myKits.push_back(kit);
//	//emptyKits.push( (Kit*) k);
//	//amount = numberToBuild; 
//	tellGuiKitReady( kitRecipe );
//
//	stateChanged();
//}
//
////From Kit Robot
//void ConveyorAgent::msgHereIsFinishedKit(KitInterface* k, InspectorKitState kitState)
//{
//	print("ConveyorAgent::msgHereIsFinishedKit");
//	/*
//	if (kitState == Good)
//	{
//		finishedGoodKits.push_back( (Kit *) k );
//		
//		//finishedGoodKits.erase(((Kit*) k);
//	}
//	else if (kitState == Bad)
//	{
//		finishedBadKits.push_back((Kit *) k);
//		//finishedBadKits.remove((Kit*) k);
//		/*
//		for (int i = 0; i < finishedBadKits.size(); i++)
//		{
//			if (finishedBadKits.at(i) == k)
//			{
//				finishedBadKits.erase(finishedBadKits.begin() + i);
//				break;
//			}
//		}
//		*/
//	//}
//	//state = ConveyorAgentState::None;
//	/*
//	for (std::list<MyKit*>::iterator it = myKits.begin(); it != myKits.end(); it++)
//	{
//		if ( (*it)->kit == ( (Kit*) k ))
//		{
//			(*it)->state = this->BeginningOfConveyor;
//		}
//	}
//	*/
//	MyKit *kit = new MyKit( (Kit*)k, BeginningOfConveyor);
//	myKits.push_back(kit);
//	stateChanged();
//}
//// called by KiTRobot
//void ConveyorAgent::msgKitPickedUp()
//{
//	print("ConveyorAgent::msgKitPickedUp");
//	/*
//	emptyKits.pop();
//	tellGuiKitTaken();
//	//state = ConveyorAgentState::None;
//	myKits.pop_front();
//	*/
//	MyKit* kit = findKitByStatus(WaitingForKitRobot);
//	kit->state = PickedUp;
//	stateChanged();
//}
//
//QPoint ConveyorAgent::getPickUpKitPosition()
//{
//	print("ConveyorAgent::getPickUpKitPosition");
//	//return this->guiConveyor->get
//	/*if (state = DroppingOffKit) {
//		return QPoint(xPos, yPos);
//	}*/
//
//	return this->guiConveyor->getPickUpKitPosition();
//}
//
//QPoint ConveyorAgent::getDropOffKitPosition() {
//	print("ConveyorAgent::getDropOffKitPosition");
//	/*if (state = DroppingOffFinishedKit) {
//		return QPoint(xPos, yPos);
//	}*/
//
//	return this->guiConveyor->getDropOffKitPosition();
//}
//
////From GUI
//void ConveyorAgent::msgGUIKitLocation(int x, int y) {
//	print("ConveyorAgent::msgGUIKitLocation");
//	xPos = x;
//	yPos = y;
//	if (state = ConveyorAgentState::None) {
//		state = DroppingOffKit;
//	}
//	else if (state = DroppingOffKit) {
//		state = DroppingOffFinishedKit;
//	}
//	return;
//}
//
//bool ConveyorAgent::pickAndExecuteAnAction()
//{
//	MyKit* kit = NULL;
//
//	kit = findKitByStatus(EndOfConveyor);
//	if(kit != NULL) 
//	{
//		tellKitRobotToTakeKit(kit);
//		return true;
//	}
//
//	kit = findKitByStatus(PickedUp);
//	if (kit != NULL)
//	{
//		tellGuiKitTaken(kit);
//		return true;
//	}
//
//	//kit = findKitByStatus(BeginningOfConveyor);
//	for ( int i = 0; i < myRecipes.size(); ++i )
//	{
//		if ( myRecipes.at( i ).state == KitState::BeginningOfConveyor )
//		{
//			this->tellGuiKitReady( &myRecipes.at( i ).recipe );
//			myRecipes.at( i ).state = EndOfConveyor;
//		}
//	}
//	if (kit != NULL)
//	{
//		tellGuiToSendOutGoodKit(kit);
//		return true;
//	}
//
//
//	/*
//	if (emptyKits.size() > 0) {
//		tellKitRobotToTakeKit(emptyKits.front());
//
//		return true;
//	}
//	
//	else if (finishedGoodKits.size() > 0) {
//		tellGuiToSendOutGoodKit(finishedGoodKits.front());
//		giveFinishedKitToFCS(finishedGoodKits.front());
//
//		return true;
//	}
//
//	else if (finishedBadKits.size() > 0) {
//		tellGuiToSendOutBadKit(finishedBadKits.front());
//		giveFinishedKitToFCS(finishedBadKits.front());
//		return true;
//	}
//
//	else if (state == DroppingOffFinishedKit) {
//		giveKitRobotKitLocation();
//		return true;
//	}
//	*/
//	return false;
//}
//
////Actions
//
////To Kit Robot
//void ConveyorAgent::tellKitRobotToTakeKit(MyKit* k){ //dropping off kit
//	print("ConveyorAgent::tellKitRobotToTakeKit");
//	kitRobot->msgHereIsKit(k->kit);
//	k->state = this->WaitingForKitRobot;
//	//emptyKits.pop();
//}
//
//QPoint ConveyorAgent::giveKitRobotKitLocation() { //dropping off finished kit
//	print("ConveyorAgent::giveKitRobotKitLocation");
//	return getDropOffKitPosition();
//}
//	
////To FCS
//void ConveyorAgent::giveFinishedKitToFCS(Kit* k)
//{
//	print("ConveyorAgent::giveFinishedKitToFCS");
//	FCS->msgHereIsFinishedKit(k);
//	for (int i = 0; i < finishedGoodKits.size(); i++)
//	{
//		if (finishedGoodKits.at(i) == k)
//		{
//			finishedGoodKits.erase(finishedGoodKits.begin() + i);
//			break;
//		}
//	}
//}
//
////To GUI
//void ConveyorAgent::tellGuiToSendOutGoodKit(MyKit* k)
//{
//	print("ConveyorAgent::tellGuiToSendOutGoodKit");
//	if (guiConveyor != NULL)
//	{
////		guiConveyor->sendGoodKitOut(k->kit);
//	}
//
//	k->state = Moving;
//}
//
//void ConveyorAgent::tellGuiToSendOutBadKit(Kit* k)
//{
//	print("ConveyorAgent::tellGuiToSendOutBadKit");
////	guiConveyor->sendBadKitOut(k);
//}
//
//void ConveyorAgent::tellGuiKitReady(KitRecipe* kitRecipe)
//{
//	print("ConveyorAgent::tellGuiKitReady");
//	if (guiConveyor != NULL)
//	{
////		guiConveyor->kitisReady(k, amt);
//		guiConveyor->DoCreateKit( (*kitRecipe) );
//	}
//}
//
//void ConveyorAgent::tellGuiKitTaken(MyKit* kit)
//{
//	print("ConveyorAgent::tellGuiKitTaken");
////	guiConveyor->kitTaken();
//	myKits.remove(kit);
//}
//
//std::string ConveyorAgent::toString() const
//{
//	return "Conveyor " + getName();
//}
//
//// Setters
//void ConveyorAgent::setFCS(FactoryControlSystemAgent * fcs)
//{
//	FCS = fcs;
//}
//
//void ConveyorAgent::setGUI(GUIConveyor* gc)
//{
//	guiConveyor = gc;
//}
//
//ConveyorAgent::MyKit* ConveyorAgent::findKitByStatus(KitState status)
//{
//	//ScopedLock scopedKitListLock (&kitsListLock);
//	for (std::list<MyKit*>::iterator it = myKits.begin(); it != myKits.end(); it++)
//	{
//		if ( (*it)->state == status)
//		{
//			return (*it);
//		}
//	}
//
//	return NULL;
//}
////#include "ConveyorAgent.h"
////
////ConveyorAgent::ConveyorAgent(KitRobotAgent* kitRobot, FactoryControlSystemAgent* FCS, GUIConveyor* gui)
////	: Agent("Conveyor") {
////	kitRobot = kr;
////	FCS = factControlSys;
////	guiConveyor = gui;
////}
////
////ConveyorAgent::~ConveyorAgent() {
////}
////	
//////Messages
////	
//////From FCS
////void msgHereAreKits(Kit* k, int numberToBuild) {
////	emptyKits.push(k);
////	//amount = numberToBuild; 
////	tellGuiKitReady(k, numberToBuild);
////}
////
//////From Kit Robot
////void msgHereIsFinishedKit(Kit* k, InspectorKitState kitState) {
////	if (kitState == Good) {
////		finishedGoodKits.remove(k);
////	}
////	else if (kitState == Bad) {
////		finishedBadKits.remove(k);
////	}
////}
////
////void msgKitPickedUP() {
////	emptyKits.pop();
////	tellGuiKitTaken();
////}
////
////virtual QPoint* getPickUpKitPosition() {
////	if (State = DroppingOffKit) {
////		return QPoint(*x,*y);
////	}
////}
////
////virtual QPoint* getDropOffKitPosition() {
////	if (State = DroppingOffKit) {
////		return QPoint(*x,*y);
////	}
////}
////
//////From GUI
////void msgGUIKitLocation(int x, int y) {
////	State = DroppingOffKit;
////}
////
////virtual bool pickAndExecuteAnAction() {
////	if (
////	if (emptyKits.size() > 0) {
////		tellKitRobotToTakeKit(emptyKit.front());
////	}
////	
////	else if (finishedGoodKits.size() > 0) {
////		tellGuiToSendOutGoodKit(finishedGoodKits.front());
////		giveFinishedKitToFCS(finishedGoodKits.front());
////	}
////
////	else if (finishedBadKits.size() > 0) {
////		tellGuiToSendOutBadKit(finishedBadKits.front());
////		giveFinishedKitTofcs(finishedBadKits.front());
////	}
////
////	else if (State == DroppingOffFinishedKits) {
////		giveKitRobotKitLocation();
////	}
////}
////
//////Actions
////
//////To Kit Robot
////void tellKitRobotToTakeKit(Kit* k){
////	kitRobot->msgHereIsKit(k);
////}
////
////void giveKitRobotKitLocation() {
////	kitRobot->getDropOffKitPosition();
////}
////	
//////To FCS
////void giveFinishedKitToFCS(Kit* k) {
////	FCS.msgHereIsFinishedKit(k);
////}
////
//////To GUI
////void tellGuiToSendOutGoodKit(Kit* k) {
////	guiConveyor->sendGoodKitOut(k);
////}
////
////void tellGuiToSendOutBadKit(Kit* k) {
////	guiConveyor->sendBadKitOut(k);
////}
////
////void tellGuiKitReady(Kit* k, int amt) {
////	guiConveyor->kitIsReady(k, amt);
////}
////
////void tellGuiKitTaken() {
////	guiConveyor->kitTaken();
////}